home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 8352 / 8352.xpi / chrome / greasefire.jar / content / picker.js < prev    next >
Text File  |  2009-05-13  |  9KB  |  332 lines

  1. /*
  2.  * Copyright (C) 2008 by Steve Krulewitz <skrulx@gmail.com>
  3.  * Licensed under GPLv2 or later, see file LICENSE in the xpi for details.
  4.  */
  5. const Cc = Components.classes;
  6. const Ci = Components.interfaces;
  7. const Cr = Components.results;
  8. const Cu = Components.utils;
  9.  
  10. function GF_Trim(s) {
  11.   return s.replace(/^\s\s*/, "").replace(/\s\s*$/, "");
  12. }
  13.  
  14. const US_BASE = "http://greasefire.userscripts.org/scripts/";
  15.  
  16. function $(id) {
  17.   return document.getElementById(id);
  18. }
  19.  
  20. function getWebProgress(aIframe) {
  21.   var wp = aIframe.docShell.QueryInterface(Ci.nsIInterfaceRequestor)
  22.                .getInterface(Ci.nsIWebProgress);
  23.   return wp;
  24. }
  25.  
  26. var PickerController = {
  27.  
  28.   _list: null,
  29.   _info: null,
  30.   _source: null,
  31.   _tabpanels: null,
  32.   _scriptInfoLoaded: false,
  33.   _scriptSourceLoaded: false,
  34.   _busyCount: 0,
  35.  
  36.   init: function PickerController_init() {
  37.  
  38.     var params = window.arguments[0].QueryInterface(Ci.nsIDialogParamBlock);
  39.     this._results = params.objects.queryElementAt(0, Ci.nsIArray);
  40.     var uri = params.objects.queryElementAt(1, Ci.nsIURI);
  41.  
  42.     document.title = "Scripts for \"" + uri.spec + "\"";
  43.  
  44.     this._install = $("install");
  45.  
  46.     this._list = $("list");
  47.     this._view = new ResultsView(this._results);
  48.     this._list.view = this._view;
  49.     this._list.addEventListener("select", this, false);
  50.  
  51.     var flags = Ci.nsIWebProgress.NOTIFY_STATE_REQUEST;
  52.  
  53.     this._info = $("info");
  54.     this._info.addEventListener("click", this, false);
  55.     var wp = getWebProgress(this._info);
  56.     wp.addProgressListener(this, flags);
  57.  
  58.     this._source = $("source");
  59.     wp = getWebProgress(this._source);
  60.     wp.addProgressListener(this, flags);
  61.  
  62.     this._tabpanels = $("tabpanels");
  63.     this._tabpanels.addEventListener("select", this, false);
  64.  
  65.     if (this._results.length > 0) {
  66.       this._list.view.selection.select(0);
  67.     }
  68.   },
  69.  
  70.   installSelected: function () {
  71.  
  72.     var index = this._list.view.selection.currentIndex;
  73.     var info = this._view.getInfo(index);
  74.  
  75.     var ios = Cc["@mozilla.org/network/io-service;1"]
  76.                 .getService(Ci.nsIIOService);
  77.  
  78.     var uriSpec = US_BASE + "source/" + info.scriptId + ".user.js";
  79.     var uri = ios.newURI(uriSpec, null, null);
  80.  
  81.     window.opener.GM_BrowserUI.startInstallScript(uri, false);
  82.   },
  83.  
  84.   updateFilter: function() {
  85.     var filter = $("filter").value;
  86.     var a = GF_Trim(filter).split(" ");
  87.     this._view.setFilter(a);
  88.   },
  89.  
  90.   handleEvent: function (aEvent) {
  91.     // This select event is for either the result list or tab panel.
  92.     if (aEvent.type == "select") {
  93.       // If the list selection changed, clear the load flags.
  94.       if (aEvent.target.id == "list") {
  95.         this._scriptInfoLoaded = false;
  96.         this._scriptSourceLoaded = false;
  97.       }
  98.       var index = this._list.view.selection.currentIndex;
  99.       var info = this._view.getInfo(index);
  100.       this._scriptSelected(info);
  101.       return true;
  102.     }
  103.  
  104.     if (aEvent.type == "click") {
  105.       var target = aEvent.target;
  106.       if ((target instanceof HTMLAnchorElement ||
  107.            target instanceof HTMLAreaElement ||
  108.            target instanceof HTMLLinkElement) &&
  109.           target.hasAttribute("href")) {
  110.         aEvent.preventDefault();
  111.         var href = target.getAttribute("href");
  112.  
  113.         var ios = Cc["@mozilla.org/network/io-service;1"]
  114.                     .getService(Ci.nsIIOService);
  115.  
  116.         if (target.className == "userjs") {
  117.           var uri = ios.newURI(href, null, null);
  118.           window.opener.GM_BrowserUI.startInstallScript(uri, false);
  119.           return false;
  120.         }
  121.  
  122.         // HACK: remove the greasefire subdomain from the URL so
  123.         // clicked linkes go back to http://userscripts.org
  124.         var currentUrl = $("url").value;
  125.         currentUrl = currentUrl.replace("http://greasefire.", "http://");
  126.  
  127.         var url = ios.newURI(currentUrl, null, null);
  128.         var absolute = url.resolve(href);
  129.  
  130.         // Append source=greasefire so we can track clicks back to the
  131.         // main site.
  132.         absolute += absolute.indexOf("?") == -1 ? "?" : "&";
  133.         absolute += "source=greasefire";
  134.         openURL(absolute);
  135.         return false;
  136.       }
  137.     }
  138.  
  139.   },
  140.  
  141.   _scriptSelected: function (aInfo) {
  142.     this._install.label = "Install \"" + aInfo.name + "\"";
  143.  
  144.     if (this._tabpanels.selectedPanel.id == "info_panel") {
  145.       this._loadInfo(aInfo);
  146.     } else {
  147.       this._loadSource(aInfo);
  148.     }
  149.   },
  150.  
  151.   _loadInfo: function (aInfo) {
  152.     var uri = US_BASE + "show/" + aInfo.scriptId;
  153.     $("url").value = uri;
  154.     if (this._scriptInfoLoaded) {
  155.       return;
  156.     }
  157.     this._info.webNavigation.loadURI(uri,
  158.                                      Ci.nsIWebNavigation.LOAD_FLAGS_NONE,
  159.                                      null,
  160.                                      null,
  161.                                      null);
  162.     this._scriptInfoLoaded = true;
  163.   },
  164.  
  165.   _loadSource: function(aInfo) {
  166.     var uri = US_BASE + "review/" + aInfo.scriptId + ".txt";
  167.     $("url").value = uri;
  168.     if (this._scriptSourceLoaded) {
  169.       return;
  170.     }
  171.     this._source.webNavigation.loadURI(
  172.       uri,
  173.       Ci.nsIWebNavigation.LOAD_FLAGS_NONE,
  174.       null,
  175.       null,
  176.       null);
  177.     this._scriptSourceLoaded = true;
  178.   },
  179.  
  180.   // nsIWebProgressListener
  181.   onStateChange: function (aWebProgress, aRequest,  aStateFlags, aStatus) {
  182.  
  183.     if (aStateFlags & Ci.nsIWebProgressListener.STATE_START) {
  184.       this._busyCount++;
  185.     }
  186.  
  187.     if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
  188.       this._busyCount--;
  189.     }
  190.  
  191.     $("throbber").className = this._busyCount ? "throbber-throb" : "throbber";
  192.   },
  193.  
  194.   QueryInterface: function (aIID) {
  195.     if (!aIID.equals(Ci.nsISupports) &&
  196.         !aIID.equals(Ci.nsIDOMEventListener) &&
  197.         !aIID.equals(Ci.nsIWebProgressListener) &&
  198.         !aIID.equals(Ci.nsISupportsWeakReference))
  199.       throw Components.results.NS_ERROR_NO_INTERFACE;
  200.  
  201.     return this;
  202.   }
  203.  
  204. }
  205.  
  206. function ResultsView(aResults) {
  207.  
  208.   this._a = [];
  209.   this._view = [];
  210.   for (var i = 0; i < aResults.length; i++) {
  211.     var result = aResults.queryElementAt(i, Ci.gfISearchResult);
  212.     this._a.push(result);
  213.     this._view.push(i);
  214.   }
  215.   this._sort();
  216. }
  217.  
  218. ResultsView.prototype = {
  219.   _treebox: null,
  220.   _selection: null,
  221.   _currentSort: "scriptrank",
  222.   _sorts: {
  223.     scriptname: true,
  224.     scriptrank: false
  225.   },
  226.   getInfo: function (row) {
  227.     return this._a[this._view[row]];
  228.   },
  229.   get rowCount() {
  230.     return this._view.length;
  231.   },
  232.   getCellText: function (row, column) {
  233.     var result = this._a[this._view[row]];
  234.     switch(column.id) {
  235.       case "scriptname":     return result.name;
  236.       case "scriptmatch":    return result.match;
  237.       case "scriptinstalls": return result.installs;
  238.       case "scriptupdated":
  239.         return (new Date(result.updated)).toLocaleDateString();
  240.       case "scriptrank":     return result.rank;
  241.     }
  242.   },
  243.   getCellValue: function (row, column) {
  244.     return this._a[this._view[row]].rank * 100;
  245.   },
  246.   getProgressMode: function (row, column) {
  247.     return Ci.nsITreeView.PROGRESS_NORMAL;
  248.   },
  249.   cycleHeader: function (column) {
  250.     var dir = this._sorts[column.id];
  251.     this._sorts[column.id] = !dir;
  252.     this._currentSort = column.id;
  253.     this._sort();
  254.     this._treebox.invalidate();
  255.   },
  256.   setFilter: function (filter) {
  257.     var oldLength = this._view.length;
  258.     this._view = [];
  259.     if (filter == "") {
  260.       for (var i = 0; i < this._a.length; i++) {
  261.         this._view.push(i);
  262.       }
  263.     }
  264.     else {
  265.       this._a.forEach(function (e, idx) {
  266.         for (var i = 0; i < filter.length; i++) {
  267.           if (e.name.toLowerCase().indexOf(filter[i]) < 0) {
  268.             return;
  269.           }
  270.         }
  271.         this._view.push(idx);
  272.       }, this);
  273.     }
  274.  
  275.     this._treebox.beginUpdateBatch();
  276.     try {
  277.       this._treebox.rowCountChanged(0, this._view.length - oldLength);
  278.       this._sort();
  279.       this._selection.select(0);
  280.     }
  281.     finally {
  282.       this._treebox.endUpdateBatch();
  283.     }
  284.   },
  285.   _sort: function () {
  286.  
  287.     var colId = this._currentSort;
  288.     var direction = this._sorts[colId];
  289.  
  290.     var _a = this._a;
  291.     var cmp = function (aidx, bidx) {
  292.  
  293.       function getValue(o) {
  294.         switch(colId) {
  295.           case "scriptname":     return o.name.toLowerCase();
  296.           case "scriptmatch":    return o.match;
  297.           case "scriptinstalls": return o.installs;
  298.           case "scriptupdated":  return o.updated;
  299.           case "scriptrank":     return o.rank;
  300.         }
  301.       }
  302.  
  303.       var a = _a[aidx];
  304.       var b = _a[bidx];
  305.       if (getValue(a) < getValue(b)) {
  306.         return direction ? -1 : 1;
  307.       }
  308.       if (getValue(a) > getValue(b)) {
  309.         return direction ? 1 : -1;
  310.       }
  311.       return 0;
  312.     }
  313.  
  314.     this._view.sort(cmp);
  315.   },
  316.   get selection() {
  317.     return this._selection;
  318.   },
  319.   set selection(selection) {
  320.     this._selection = selection;
  321.   },
  322.   setTree: function (treebox) { this._treebox = treebox; },
  323.   isContainer: function (row) { return false; },
  324.   isSeparator: function (row) { return false; },
  325.   isSorted: function () { return false; },
  326.   getLevel: function (row) { return 0; },
  327.   getImageSrc: function (row, col) { return null; },
  328.   getRowProperties: function (row, props) {},
  329.   getCellProperties: function (row, col, props) {},
  330.   getColumnProperties: function (colid, col, props) {}
  331. };
  332.